#include "LevelManager.h"
#include <QStandardPaths>
#include <QDebug>

LevelManager::LevelManager(QObject *parent)
    : QObject(parent)
{
    // 设置关卡文件路径
    QString dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
    QDir dir(dataDir);
    if (!dir.exists()) {
        dir.mkpath(".");
    }
    m_levelsFilePath = dir.filePath("levels.json");
    
    // 加载或初始化关卡
    if (!loadLevels()) {
        initializeDefaultLevels();
        saveLevels();
    }
}

bool LevelManager::loadLevels()
{
    QFile file(m_levelsFilePath);
    if (!file.open(QIODevice::ReadOnly)) {
        qDebug() << "Cannot open levels file:" << m_levelsFilePath;
        return false;
    }
    
    QByteArray data = file.readAll();
    file.close();
    
    QJsonDocument doc = QJsonDocument::fromJson(data);
    if (doc.isNull() || !doc.isArray()) {
        qDebug() << "Invalid levels file format";
        return false;
    }
    
    QJsonArray levelsArray = doc.array();
    m_levels.clear();
    
    for (const QJsonValue &levelValue : levelsArray) {
        QJsonObject levelObj = levelValue.toObject();
        SudokuLevel level;
        
        level.levelId = levelObj["id"].toInt();
        level.name = levelObj["name"].toString();
        level.difficulty = levelObj["difficulty"].toInt();
        level.timeLimit = levelObj["timeLimit"].toInt();
        
        // 读取谜题
        QJsonArray puzzleArray = levelObj["puzzle"].toArray();
        for (int i = 0; i < puzzleArray.size(); ++i) {
            QJsonArray rowArray = puzzleArray[i].toArray();
            QVector<int> row;
            for (int j = 0; j < rowArray.size(); ++j) {
                row.append(rowArray[j].toInt());
            }
            level.puzzle.append(row);
        }
        
        // 读取解答
        QJsonArray solutionArray = levelObj["solution"].toArray();
        for (int i = 0; i < solutionArray.size(); ++i) {
            QJsonArray rowArray = solutionArray[i].toArray();
            QVector<int> row;
            for (int j = 0; j < rowArray.size(); ++j) {
                row.append(rowArray[j].toInt());
            }
            level.solution.append(row);
        }
        
        m_levels.append(level);
    }
    
    qDebug() << "Loaded" << m_levels.size() << "levels";
    return true;
}

bool LevelManager::saveLevels()
{
    QJsonArray levelsArray;
    
    for (const SudokuLevel &level : m_levels) {
        QJsonObject levelObj;
        levelObj["id"] = level.levelId;
        levelObj["name"] = level.name;
        levelObj["difficulty"] = level.difficulty;
        levelObj["timeLimit"] = level.timeLimit;
        
        // 保存谜题
        QJsonArray puzzleArray;
        for (const QVector<int> &row : level.puzzle) {
            QJsonArray rowArray;
            for (int value : row) {
                rowArray.append(value);
            }
            puzzleArray.append(rowArray);
        }
        levelObj["puzzle"] = puzzleArray;
        
        // 保存解答
        QJsonArray solutionArray;
        for (const QVector<int> &row : level.solution) {
            QJsonArray rowArray;
            for (int value : row) {
                rowArray.append(value);
            }
            solutionArray.append(rowArray);
        }
        levelObj["solution"] = solutionArray;
        
        levelsArray.append(levelObj);
    }
    
    QJsonDocument doc(levelsArray);
    QFile file(m_levelsFilePath);
    if (!file.open(QIODevice::WriteOnly)) {
        qDebug() << "Cannot save levels file:" << m_levelsFilePath;
        return false;
    }
    
    file.write(doc.toJson());
    file.close();
    
    qDebug() << "Saved" << m_levels.size() << "levels to" << m_levelsFilePath;
    return true;
}

void LevelManager::initializeDefaultLevels()
{
    m_levels.clear();
    
    // 生成一些默认关卡
    for (int i = 1; i <= 10; ++i) {
        SudokuLevel level;
        level.levelId = i;
        level.name = QString("关卡 %1").arg(i);
        level.difficulty = (i - 1) / 2 + 1; // 1-5 难度
        level.timeLimit = 1800; // 30分钟
        
        generateRandomLevel(level.difficulty, i);
        
        // 获取刚刚生成的关卡
        if (i <= m_levels.size()) {
            // 已经通过 generateRandomLevel 添加了
        }
    }
}

void LevelManager::generateRandomLevel(int difficulty, int levelId)
{
    SudokuLevel level;
    
    if (levelId == -1) {
        level.levelId = m_levels.size() + 1;
    } else {
        level.levelId = levelId;
    }
    
    level.name = QString("随机关卡 %1").arg(level.levelId);
    level.difficulty = difficulty;
    level.timeLimit = 1800;
    
    generateSudokuPuzzle(difficulty, level.puzzle, level.solution);
    
    // 如果指定了levelId，检查是否已存在并替换
    if (levelId != -1) {
        for (int i = 0; i < m_levels.size(); ++i) {
            if (m_levels[i].levelId == levelId) {
                m_levels[i] = level;
                return;
            }
        }
    }
    
    m_levels.append(level);
}

void LevelManager::generateSudokuPuzzle(int difficulty, 
                                       QVector<QVector<int>> &puzzle, 
                                       QVector<QVector<int>> &solution)
{
    // 初始化空白数独
    puzzle = QVector<QVector<int>>(9, QVector<int>(9, 0));
    solution = QVector<QVector<int>>(9, QVector<int>(9, 0));
    
    // 生成完整解
    solveSudoku(solution);
    
    // 根据难度移除数字
    int cellsToRemove;
    switch(difficulty) {
        case 1: cellsToRemove = 30; break; // 简单
        case 2: cellsToRemove = 40; break; // 中等
        case 3: cellsToRemove = 50; break; // 困难
        case 4: cellsToRemove = 55; break; // 专家
        case 5: cellsToRemove = 60; break; // 大师
        default: cellsToRemove = 40;
    }
    
    puzzle = solution;
    
    // 随机移除数字
    int removed = 0;
    int attempts = 0;
    const int maxAttempts = 200;
    
    while (removed < cellsToRemove && attempts < maxAttempts) {
        int row = QRandomGenerator::global()->bounded(9);
        int col = QRandomGenerator::global()->bounded(9);
        
        if (puzzle[row][col] != 0) {
            int backup = puzzle[row][col];
            puzzle[row][col] = 0;
            
            // 检查是否仍有唯一解（简化检查）
            QVector<QVector<int>> temp = puzzle;
            if (solveSudoku(temp)) {
                removed++;
            } else {
                puzzle[row][col] = backup;
            }
        }
        attempts++;
    }
}

bool LevelManager::solveSudoku(QVector<QVector<int>> &grid)
{
    int row, col;
    
    if (!findEmptyCell(grid, row, col)) {
        return true; // 数独已解决
    }
    
    // 尝试数字1-9
    for (int num = 1; num <= 9; num++) {
        if (isValid(grid, row, col, num)) {
            grid[row][col] = num;
            
            if (solveSudoku(grid)) {
                return true;
            }
            
            grid[row][col] = 0;
        }
    }
    return false;
}

bool LevelManager::findEmptyCell(const QVector<QVector<int>> &grid, int &row, int &col)
{
    for (row = 0; row < 9; row++) {
        for (col = 0; col < 9; col++) {
            if (grid[row][col] == 0) {
                return true;
            }
        }
    }
    return false;
}

bool LevelManager::isValid(const QVector<QVector<int>> &grid, int row, int col, int num)
{
    // 检查行
    for (int x = 0; x < 9; x++) {
        if (grid[row][x] == num) return false;
    }
    
    // 检查列
    for (int x = 0; x < 9; x++) {
        if (grid[x][col] == num) return false;
    }
    
    // 检查3x3宫格
    int startRow = row - row % 3;
    int startCol = col - col % 3;
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            if (grid[i + startRow][j + startCol] == num) return false;
        }
    }
    
    return true;
}

SudokuLevel LevelManager::getLevel(int levelId) const
{
    for (const SudokuLevel &level : m_levels) {
        if (level.levelId == levelId) {
            return level;
        }
    }
    return SudokuLevel();
}

void LevelManager::addLevel(const SudokuLevel &level)
{
    m_levels.append(level);
    saveLevels();
}

bool LevelManager::removeLevel(int levelId)
{
    for (int i = 0; i < m_levels.size(); ++i) {
        if (m_levels[i].levelId == levelId) {
            m_levels.removeAt(i);
            saveLevels();
            return true;
        }
    }
    return false;
}